/*************************************************************************  
 *   This file is part of UBBMPSREADER.
 *
 *   UBBMPSREADER is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   UBBMPSREADER is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with UBBMPSREADER.  If not, see <http://www.gnu.org/licenses/>. 
 *************************************************************************/

package cs.ubbcluj.ro.datatypes.implementations;

import cs.ubbcluj.ro.datatypes.interfaces.*;

public strictfp abstract class AbstractMatrix implements Matrix {
	
    public void set(Matrix m) {
    	for (int i = 0; i < m.getNrOfRows(); i++) {
    	    for (int j = 0; j < m.getNrOfColumns(); j++)
    		try {
    		    addElement(i, j, m.get(i, j));
    		} catch (final InterruptedException e) {
    		    System.out.println(e);
    		    System.exit(1);
    		}
        }
    }
	
    public Matrix sum(Matrix m) throws InterruptedException {
    	Matrix result = createHelperMatrix(this.getNrOfRows(), this.getNrOfColumns());
    	
		if ((getNrOfRows() != m.getNrOfRows()) && (getNrOfColumns() != m.getNrOfColumns())) {
		    throw new InterruptedException("The given matrices have different sizes");
		} else {
		    for (int i = 0; i < getNrOfRows(); i++) {
			for (int j = 0; j < getNrOfColumns(); j++)
			    result.set(i, j, get(i, j) + m.get(i, j));
		    }
		    return result;
		}
    }
    
    public void scalarProductColumn(final int i, final double d) {
		for (int j = 0; j < getNrOfRows(); j++) {
		    try {
				addElement(j, i, get(j, i) * d);
		    } catch (final InterruptedException e) {
		    	System.out.println(e);
		    	System.exit(1);
		    }
		}
    }
    
    public Matrix product(double n) {
    	Matrix result = createHelperMatrix(this.getNrOfRows(), this.getNrOfColumns());
    	
    	for (int i = 0; i < getNrOfRows(); i++) {
    	    for (int j = 0; j < getNrOfColumns(); j++)
    		try {
    		    result.set(i, j, get(i, j) * n);
    		} catch (final InterruptedException e) {
    		    System.out.println(e);
    		    System.exit(1);
    		}
    	}
    	return result;
    }

	public Matrix product(Matrix m) throws InterruptedException {
		Matrix result = createHelperMatrix(this.getNrOfRows(), m.getNrOfColumns());
		
		if (getNrOfColumns() != m.getNrOfRows())
		    throw new InterruptedException("The given matrices have different sizes");
		else {
		    for (int i = 0; i < getNrOfRows(); i++) {
		    	for (int j = 0; j < m.getNrOfColumns(); j++) {
				    double product = 0;
				    	for (int k = 0; k < getNrOfColumns(); k++) {
				    		product += get(i, k) * m.get(k, j);
				    	}
				    	result.set(i, j, product);
		    	}
		    }
		    return result;
		}
    }

    public Vector product(Vector v) throws InterruptedException {
    	//System.out.println("szam"+v.getNrOfRows()+" "+getNrOfColumns());
    	Vector result = v.createHelperVector(this.getNrOfRows());
    	if (getNrOfColumns() != v.getNrOfRows()) {
		    throw new InterruptedException("The given matrix and vector have different sizes");
		} else {
		    double sum;
		    for (int i = 0; i < getNrOfRows(); i++) {
		    	sum = 0;
		    	for (int j = 0; j < v.getNrOfRows(); j++) {
		    		sum += get(i, j) * v.get(j);
		    	}
		    	result.set(i, sum);
		    }
		    return result;
		}
    }

    public Matrix divElement(int n) {
	double value = 0;
	for (int i = 0; i < getNrOfRows(); i++)
	    for (int j = 0; j < getNrOfColumns(); j++) {
		try {
		    value= get(i, j);
		} catch (final InterruptedException e) {
		    System.out.println(e);
		    System.exit(1);
		}
		if (value == 0)
		    addElement(i, j, value);
		else
		    addElement(i, j, (n / value));
	    }
	return this;
    }
    
    public void print() {
    	for (int i = 0; i < getNrOfRows(); i++) {
    		for (int j = 0; j < getNrOfColumns(); j++) {
    			try {
					System.out.print(get(i, j) + " ");
				} catch (InterruptedException e) {					
					e.printStackTrace();
				}
    		}
    		System.out.println();
    	}
    }
}
